//
//  EXNavigationController.m
//  Exercise
//
//  Created by 羊谦 on 16/5/31.
//  Copyright © 2016年 NetEase-yangqian. All rights reserved.
//

#import "EXNavigationController.h"
#import <objc/runtime.h>


static const void * const kUIViewControllerPushFinishedBlock = &kUIViewControllerPushFinishedBlock;
NSString *const HSNavigationPopedByGestureNotification = @"HSNavigationPopedByGestureNotification";
NSString *const HSNavigationPopedByGestureFromControllerKey = @"HSNavigationPopedByGestureFromControllerKey";


typedef void (^EXNavigationPushBlock)(void);

@interface UIViewController (NavigationPushFinish)
@property (nonatomic,copy) EXNavigationPushBlock pushFinishedBlock;
@end

@implementation UIViewController (NavigationPushFinish)
- (EXNavigationPushBlock)pushFinishedBlock
{
    return objc_getAssociatedObject(self, kUIViewControllerPushFinishedBlock);
}

- (void)setPushFinishedBlock:(EXNavigationPushBlock)pushFinishedBlock
{
    objc_setAssociatedObject(self, kUIViewControllerPushFinishedBlock, pushFinishedBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
@end

@interface EXNavigationController ()<UINavigationControllerDelegate,UIGestureRecognizerDelegate>
{
@private
    NSNotification *_gestureNotification;
    __weak id<UINavigationControllerDelegate> _navigationDelegate;
}
@property (nonatomic,strong) NSNotification *gestureNotification;
@property (nonatomic,strong) UIImageView *lineView;//navigationbar横线
@end



@implementation EXNavigationController

@synthesize gestureNotification = _gestureNotification;
@dynamic delegate;

#pragma mark - lifecycle
- (instancetype)initWithRootViewController:(UIViewController *)rootViewController
{
    self = [super initWithRootViewController:rootViewController];
    if (self)
    {
        self.navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName : [UIColor colorWithHexString:@"333333"],
                                                   NSFontAttributeName : [UIFont fontWithName:@"Arial" size:18]};
        self.navigationBar.tintColor = [UIColor colorWithHexString:@"333333"];
        [self.navigationBar setBackgroundImage:[UIImage imageWithColor:[UIColor colorWithHexString:@"fedc2e"]] forBarMetrics:UIBarMetricsDefault];
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.lineView = [self changeNavigationBackground:self.navigationBar];
    self.interactivePopGestureRecognizer.delegate = self;
    [super setDelegate:self];
    
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    self.lineView.hidden = YES;
}

//找到navigationBar的分割线
- (UIImageView *)changeNavigationBackground:(UIView *)view {
    if ([view isKindOfClass:[UIImageView class]] && view.bounds.size.height<=1.0) {
        return (UIImageView *)view;
    }
    for (UIView *subview in view.subviews) {
        UIImageView *imageView = [self changeNavigationBackground:subview];
        if (imageView) {
            return imageView;
        }
    }
    return nil;
}

#pragma mark - gesture
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    if (gestureRecognizer == self.interactivePopGestureRecognizer)
    {
        NSUInteger topIndex = [self.viewControllers indexOfObject:self.topViewController];
        if (topIndex == 0)
        {
            return NO;
        }
        return YES;
    }
    return NO;
}

#pragma mark - delegate
- (void)setDelegate:(id<UINavigationControllerDelegate>)delegate
{
    //外部无法设置super的delegate
    _navigationDelegate = delegate;
}

- (id<UINavigationControllerDelegate>)navigationDelegate
{
    return _navigationDelegate;
}

#pragma mark - public
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    if ([self.viewControllers containsObject:viewController])
    {
        NSMutableArray *array = [self.viewControllers mutableCopy];
        if ([array lastObject] == viewController)
        {
            return;
        }
        else
        {
            [array removeObject:viewController];
            self.viewControllers = array;
        }
    }
    self.interactivePopGestureRecognizer.enabled = NO;
    if (self.showTabbarInRootViewOnly)
    {
        viewController.hidesBottomBarWhenPushed = YES;
    }
    [super pushViewController:viewController animated:animated];
}

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated finished:(EXNavigationPushBlock)finishedBlock
{
    viewController.pushFinishedBlock = finishedBlock;
    [self pushViewController:viewController animated:animated];
}

- (void)setViewControllers:(NSArray *)viewControllers
{
    if (self.showTabbarInRootViewOnly)
    {
        for (UIViewController *viewController in viewControllers)
        {
            viewController.hidesBottomBarWhenPushed = viewController != [viewControllers firstObject];
        }
    }
    [super setViewControllers:viewControllers];
}

#pragma mark - UINavigationControllerDelegate
- (id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
                                   animationControllerForOperation:(UINavigationControllerOperation)operation
                                                fromViewController:(UIViewController *)fromVC
                                                  toViewController:(UIViewController *)toVC
{
    BOOL userGesture = (self.interactivePopGestureRecognizer.state == UIGestureRecognizerStateBegan);
    if (operation == UINavigationControllerOperationPop && userGesture)
    {
        NSDictionary *userInfo = nil;
        if (fromVC)
        {
            userInfo = @{HSNavigationPopedByGestureFromControllerKey:fromVC};
        }
        NSNotification *notification = [[NSNotification alloc] initWithName:HSNavigationPopedByGestureNotification object:self userInfo:userInfo];
        self.gestureNotification = notification;
    }
    else
    {
        self.gestureNotification = nil;
    }
    
    if ([_navigationDelegate respondsToSelector:@selector(navigationController:animationControllerForOperation:fromViewController:toViewController:)])
    {
        return [_navigationDelegate navigationController:navigationController animationControllerForOperation:operation fromViewController:fromVC toViewController:toVC];
    }
    return nil;
}

- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    self.interactivePopGestureRecognizer.enabled = YES;
    if (self.gestureNotification)
    {
        [[NSNotificationCenter defaultCenter] postNotification:self.gestureNotification];
        self.gestureNotification = nil;
    }
    
    if (viewController.pushFinishedBlock)
    {
        viewController.pushFinishedBlock();
        viewController.pushFinishedBlock = nil;
    }
    
    if ([_navigationDelegate respondsToSelector:@selector(navigationController:didShowViewController:animated:)])
    {
        [_navigationDelegate navigationController:navigationController didShowViewController:viewController animated:animated];
    }
}

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    if ([_navigationDelegate respondsToSelector:@selector(navigationController:willShowViewController:animated:)])
    {
        [_navigationDelegate navigationController:navigationController willShowViewController:viewController animated:animated];
    }
}

- (id <UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController
                          interactionControllerForAnimationController:(id <UIViewControllerAnimatedTransitioning>)animationController
{
    if ([_navigationDelegate respondsToSelector:@selector(navigationController:interactionControllerForAnimationController:)])
    {
        return [_navigationDelegate navigationController:navigationController interactionControllerForAnimationController:animationController];
    }
    return nil;
}


@end
